package controller

import (
	"net/http"
	"smart-flow/server/config"
	"smart-flow/server/proto"
	"smart-flow/server/service"
	"strings"

	"github.com/gin-gonic/gin"
)

func Index(c *gin.Context) {
	token, err := c.Cookie("token")
	if err != nil || token != Token {
		c.Redirect(http.StatusFound, "/sf/Home")
		return
	}
	c.HTML(http.StatusOK, "flow.html", nil)
}

func Count(c *gin.Context) {
	c.JSON(http.StatusOK, proto.NewCommonRespWithData(proto.Success, service.EnhanceCount()))
}

func Bandwidth(c *gin.Context) {
	c.JSON(http.StatusOK, proto.NewCommonRespWithData(proto.Success, service.Bandwidth()))
}

func Stop(c *gin.Context) {
	var req proto.StopReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.Isp != config.IspCustom && req.Isp != config.IspTelecom && req.Isp != config.IspMobile && req.Isp != config.IspUnicom {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	go service.Stop(req.Isp)
	c.JSON(http.StatusOK, proto.NewCommonResp(proto.Success))
}

func StopOne(c *gin.Context) {
	var req proto.StopOneReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	go service.StopOne(req.Uid)
	c.JSON(http.StatusOK, proto.NewCommonResp(proto.Success))
}

func Test(c *gin.Context) {
	var req proto.TestReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if strings.TrimSpace(req.Addr) == "" || strings.TrimSpace(req.Uid) == "" {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	go service.TestStart(req.Addr, 5, 1000, req.Uid)
	c.JSON(http.StatusOK, proto.NewCommonResp(proto.Success))
}

func Start(c *gin.Context) {
	var req proto.StartReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	duration := req.Duration
	rate := req.Rate
	limit := req.Limit
	if strings.TrimSpace(req.Addr) == "" || duration <= 0 || duration > 60 || rate < 100 || limit < 1 || limit > 100 {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	go service.CustomStart(req.Addr, limit, duration, rate)
	c.JSON(http.StatusOK, proto.NewCommonResp(proto.Success))
}

func TaskList(c *gin.Context) {
	c.JSON(http.StatusOK, proto.NewCommonRespWithData(proto.Success, service.TaskList()))
}

func AddTask(c *gin.Context) {
	var req proto.AddTaskReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.Isp != config.IspTelecom && req.Isp != config.IspMobile && req.Isp != config.IspUnicom {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.RunCycle < 0 || req.RunCycle > 1 {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.RunDuration < 0 {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.RunRate < 100 {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.V4Enabled == 0 && req.V6Enabled == 0 {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if !service.TaskAdd(&req) {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.AddTaskError))
	}
	c.JSON(http.StatusOK, proto.NewCommonResp(proto.Success))
}

func DelTask(c *gin.Context) {
	var req proto.StopReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.Isp != config.IspCustom && req.Isp != config.IspTelecom && req.Isp != config.IspMobile && req.Isp != config.IspUnicom {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	service.TaskDel(req.Isp)
	c.JSON(http.StatusOK, proto.NewCommonResp(proto.Success))
}

func GetUidByIp(c *gin.Context) {
	var req proto.GetUidByIpReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if strings.TrimSpace(req.Ip) == "" {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	c.JSON(http.StatusOK, proto.NewCommonRespWithData(proto.Success, service.FindUidByIp(req.Ip)))
}

func GlobalPause(c *gin.Context) {
	var req proto.PauseReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.Isp != config.IspCustom && req.Isp != config.IspTelecom && req.Isp != config.IspMobile && req.Isp != config.IspUnicom {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	service.TaskPause(req.Isp)
	c.JSON(http.StatusOK, proto.NewCommonResp(proto.Success))
}

func GlobalResume(c *gin.Context) {
	var req proto.ResumeReq
	if c.ShouldBind(&req) != nil {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	if req.Isp != config.IspCustom && req.Isp != config.IspTelecom && req.Isp != config.IspMobile && req.Isp != config.IspUnicom {
		c.JSON(http.StatusOK, proto.NewCommonResp(proto.ParameterError))
		return
	}
	service.TaskResume(req.Isp)
	c.JSON(http.StatusOK, proto.NewCommonResp(proto.Success))
}
